home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1999 July
/
Macworld (1999-07).dmg
/
Shareware World
/
Info
/
For Developers
/
Mops 3.4.sea
/
Mops source
/
System source
/
double
next >
Wrap
Text File
|
1998-10-05
|
4KB
|
150 lines
\ Some double-number words
\ May 98 mrh initial version
\ This isn't the full ANSI Forth double-number word set, since I
\ very much doubt we need it in all its glory for a 32-bit Forth.
\ However we need some of the words for the Forth Scientific
\ Library.
\ 2SWAP is already implemented in cg6
: 2OVER
inline{ 3pick 3pick }
;
\ The following are already implemented in pnuc1, 'cause we need them in
\ the nucleus:
\
\ D+ D- DNEGATE
: D= { n1_lo n1_hi n2_lo n2_hi -- b }
n1_lo n2_lo =
n1_hi n2_hi = and ;
: D< { n1_lo n1_hi n2_lo n2_hi -- b }
n1_hi n2_hi <>
IF n1_hi n2_hi <
ELSE n1_lo n2_lo u<
THEN
;
: D0< 31 a>> nip ;
: D0= or 0= ;
: DABS dup 0< IF dnegate THEN ;
: DMAX 2dup d< IF 2swap THEN 2drop ;
: DMIN 2dup d< NIF 2swap THEN 2drop ;
: D>S inline{ drop} ;
: 2@ inline{ dup cell+ @ swap @} ;
: 2! inline{ tuck ! cell+ !} ;
: 2>R inline{ swap >r >r} ;
: 2R> inline{ r> r> swap} ;
: 2R@ inline{ r> r@ swap dup >r} ;
: D* { n1_lo n1_hi n2_lo n2_hi -- n3_lo n3_hi }
n1_lo n2_lo um* n1_lo n2_hi * + n1_hi n2_lo * + ;
: D.R { d_lo d_hi #to-right -- }
d_lo d_hi dabs
<# #s d_hi sign #>
#to-right over - spaces
type
;
: D. \ ( n -- )
0 d.r space ;
: D.H
base 16 -> base
swap .
-> base ;
: UD.
<# #s #> type space ;
endload
\ Use the following if you need to, at your own risk:
:ppc_code UMD/MOD ( uq ud1 -- ud2 ud3 )
\ unsigned quad divided by double, giving double remainder and quotient.
\ I doubt this is used much in anger, so I'm not going to bother with
\ the pre-shifting stuff, which would be a definite pain with 128 bits.
r8 0 rSP lwz, \ get dividend to r8:r7:r6:r5
r7 4 rSP lwz,
r6 8 rSP lwz,
r5 12 rSP lwz,
rSP rSP 8 addi, \ adjust rSP for what we return
r9 64 li,
r9 mtctr, \ the number of iterations = 64
\ Now for the main restoring division shift and subtract loop.
\ With each shift we subtract the divisor from the top half of
\ the 128-bit "register", but only use the result if it's positive.
\ In this case we shift in a 1 into the low bit position. Otherwise
\ we shift in a 0. This will be the next bit of the quotient.
\ At the end of the loop, we'll have the remainder in the high
\ half, and the quotient in the low half.
r10 -1 li, \ r10 = -1 for carry setting
r8 r8 0 addic, \ clear carry initially
CDP \ loop start
r5 r5 r5 adde, \ here we shift the long register
r6 r6 r6 adde, \ left one place by adding each
r7 r7 r7 adde, \ portion to itself, with carry
r8 r8 r8 adde,
r0 r3 r7 subfc, \ Subtract divisor from hi half
r9 r4 r8 subfe., \ of long register -> r9:r0
ge if, \ Result was positive, so we use it
r7 r0 mr, \ move result to hi half of long reg
r8 r9 mr,
r0 r10 1 addic, \ and set carry bit -
then, \ carry bit will come into the lo
\ bit position of the long reg on
\ the next shift.
dnz bc, \ loop
\ now we write the results. The quotient is in the lo half of the long
\ reg, but needs one more shift, bringing the carry into the lo bit.
\ At the same time we get the quotient to r4:r3, where we want it.
r3 r5 r5 adde,
r4 r6 r6 adde,
\ The remainder is in r8:r7 - we now put it back into the memory part
\ of the stack, where the original dividend came from. As we always
\ return 2 cells in registers from a code definition, we'll now
\ have the remainder under the quotient, as required.
r7 4 rSP stw,
r8 0 rSP stw,
blr,
;ppc_code
\ M*/ isn't complete yet, since it doesn't handle negative numbers.
: M*/ { n1_lo n1_hi n2 n3 \ lo mid hi -- n4_lo n4_hi }
n1_lo n2 m* -> mid -> lo
n1_hi n2 m* mid s>d d+ -> hi -> mid
lo mid hi 0 n3 0 umd/mod 2swap 2drop
;